use halo_model::ExtensionOperator;
use std::collections::{HashMap, HashSet};
use std::path::Path;
use std::sync::Arc;

use ordermap::OrderSet;
use salvo::http::form::FilePart;
use salvo::{Depot, Request, Response};
use serde::{Deserialize, Serialize};
use serde_json;
use tracing::info;

use crate::config::app_error::{AppError, AppResult};
use crate::extension::index::extension_client;
use crate::extension::index::index::query::query::query_factory;
use crate::extension::index::page_request::{Direction, Order, PageRequestImpl, Sort};
use crate::extension::index::router::list_options::ListOptions;
use crate::extension::index::router::list_result::ListResult;
use crate::extension::index::selector::field_selector::FieldSelector;
use crate::extension::index::selector::label_selector::{LabelSelector, LabelSelectorBuilder};
use crate::extension::model::role::{Role, GROUP};
use crate::extension::model::role_binding::{RoleBinding, RoleRef, Subject};
use crate::extension::model::user::{ChangePasswordRequest, UserListRequest};
use crate::extension::model::user::{
    CreateUserRequest, DetailedUser, LoginUserInfo, User, UserPermission,
    AVATAR_ATTACHMENT_NAME_ANNO, EMAIL_TO_VERIFY, LAST_AVATAR_ATTACHMENT_NAME_ANNO,
    ROLE_NAMES_ANNO,
};
use crate::extension::model::{role, role_binding};
use crate::infra::system_setting::SYSTEM_CONFIG;
use crate::infra::{env_fetcher, system_setting};
use crate::services::role as role_service;
use crate::store::extension_store_client as store_client;
use crate::store::extension_store_client::fetch;
use crate::utils::rand_utils;
use crate::utils::user_util;

use self::query_factory::Query;
// 引入serde_json库

// pub async fn add_user(req: UserAddRequest) -> AppResult<UserResponse> {
//     let db = DB.get().ok_or(anyhow::anyhow!(""))?;
//     let halo-model = user::ActiveModel {
//         id: Set(Uuid::new_v4().to_string()),
//         username: Set(req.username.clone()),
//         password: Set(rand_utils::hash_password(req.password).await?),
//     };
//     let user = User::insert(halo-model).exec(db).await?;
//     Ok(UserResponse {
//         id: user.last_insert_id,
//         username: req.username,
//     })
// }
//
// pub async fn login(req: UserLoginRequest) -> AppResult<UserLoginResponse> {
//     let db = DB.get().ok_or(anyhow::anyhow!(""))?;
//     let user = User::find()
//         .filter(user::Column::Username.eq(req.username))
//         .one(db)
//         .await?;
//     if user.is_none() {
//         return Err(anyhow::anyhow!("").into());
//     }
//     let user = user.unwrap();
//     if rand_utils::verify_password(req.password, user.password)
//         .await
//         .is_err()
//     {
//         return Err(anyhow::anyhow!("Incorrect password.").into());
//     }
//     let (token, exp) = get_token(user.username.clone(), user.id.clone())?;
//     let res = UserLoginResponse {
//         id: user.id,
//         username: user.username,
//         token,
//         exp,
//     };
//     Ok(res)
// }
//
// pub async fn update_user(req: UserUpdateRequest) -> AppResult<UserResponse> {
//     let db = DB.get().ok_or(anyhow::anyhow!(""))?;
//
//     let user = User::find_by_id(req.id).one(db).await?;
//     if user.is_none() {
//         return Err(anyhow::anyhow!("").into());
//     }
//     let mut user: user::ActiveModel = user.unwrap().into();
//
//     user.username = Set(req.username.to_owned());
//     user.password = Set(rand_utils::hash_password(req.password).await?);
//
//     let user: user::Model = user.update(db).await?;
//
//     Ok(UserResponse {
//         id: user.id,
//         username: user.username,
//     })
// }
//
// pub async fn delete_user(id: String) -> AppResult<()> {
//     let db = DB.get().ok_or(anyhow::anyhow!("数据库连接失败"))?;
//     User::delete_by_id(id).exec(db).await?;
//     Ok(())
// }
//
// pub async fn users() -> AppResult<Vec<UserResponse>> {
//     let db = DB.get().ok_or(anyhow::anyhow!(""))?;
//     let users = User::find().all(db).await?;
//     let res = users
//         .into_iter()
//         .map(|user| UserResponse {
//             id: user.id,
//             username: user.username,
//         })
//         .collect::<Vec<_>>();
//     Ok(res)
// }

pub const SELF_USER: &str = "-";
//     private static final String DEFAULT_USER_AVATAR_ATTACHMENT_POLICY_NAME = "default-policy";
pub const DEFAULT_USER_AVATAR_ATTACHMENT_POLICY_NAME: &str = "default-policy";


pub async fn me(depot: &mut Depot) -> AppResult<DetailedUser> {
    // let user = depot
    //     .get::<&str>("current_user")
    //     .copied()
    //     .unwrap_or("anonymousUser");
    let username = user_util::current_username(depot);
    info!("current_user: {}", username);
    let user = store_client::fetch(User::KIND, &username).await?;
    info!("current_user info : {:?}", user);
    to_detail_user(user).await
}

pub async fn get_user_by_name(name: String) -> AppResult<DetailedUser> {
    let user = store_client::fetch(User::KIND, &name).await?;
    to_detail_user(user).await
}

pub async fn get_user(username: String) -> AppResult<User> {
    let user = fetch(User::KIND, &username).await;
    if user.is_err() {
        return Err(anyhow::anyhow!("User {} was not found", username.clone()).into());
    }
    user
}

pub async fn update_profile(depot: &mut Depot, user: User) -> AppResult<User> {
    let current_user_name = user_util::current_username(depot);

    let username = user.get_metadata().get_name();
    if current_user_name != username {
        return Err(anyhow::anyhow!("Username didn't match.").into());
    }

    let mut current_user: User = fetch(User::KIND, &current_user_name).await?;
    let mut old_annotations = current_user
        .get_metadata()
        .get_annotations()
        .unwrap_or(HashMap::new());
    let new_annotations = user.get_metadata().get_annotations();

    if new_annotations.is_some() {
        let string = LAST_AVATAR_ATTACHMENT_NAME_ANNO.to_string();
        let mut new_annotations = new_annotations.unwrap();
        new_annotations.insert(
            string.clone(),
            old_annotations.remove(&string).unwrap_or(String::new()),
        );

        let string = AVATAR_ATTACHMENT_NAME_ANNO.to_string();
        new_annotations.insert(
            string.clone(),
            old_annotations.remove(&string).unwrap_or(String::new()),
        );

        let string = EMAIL_TO_VERIFY.to_string();
        new_annotations.insert(
            string.clone(),
            old_annotations.remove(&string).unwrap_or(String::new()),
        );

        current_user.get_metadata_mut().set_annotations(new_annotations);
    }

    let mut spec = current_user.spec.clone();

    let new_spec = user.spec;

    spec.bio = new_spec.bio;
    spec.display_name = new_spec.display_name;
    spec.two_factor_auth_enabled = new_spec.two_factor_auth_enabled;
    spec.phone = new_spec.phone;

    let _ = store_client::update(current_user.clone()).await;
    Ok(current_user)
}

pub async fn to_detail_user(user: User) -> AppResult<DetailedUser> {
    let metadata = user.get_metadata().clone();
    let annotations = metadata.get_annotations();
    let role_names_json = annotations.map_or_else(|| None, |a| a.get(ROLE_NAMES_ANNO).cloned());

    let role_name_list: Vec<String> = match role_names_json {
        Some(s) => serde_json::from_str(&s)?,
        None => Vec::new(),
    };

    let role_list = store_client::list::<Role>(role::Role::KIND, role_name_list).await?;

    Ok(DetailedUser {
        user,
        roles: role_list,
    })
}

pub async fn grant_roles(username: String, roles: &HashSet<String>) -> AppResult<User> {
    let user: User = fetch(User::KIND, &username).await?;

    let list = store_client::list_filter(
        RoleBinding::KIND,
        RoleBinding::contains_user(username.clone()),
    )
    .await?;
    let mut bindings_to_update = HashSet::new();
    let mut bindings_to_delete = HashSet::new();
    let mut existing_roles = HashSet::new();

    for mut role_binding in list {
        let role_name = role_binding.role_ref.name.clone();
        if roles.contains(&role_name) {
            existing_roles.insert(role_name);
            continue;
        }
        let subjects = &mut role_binding.subjects;
        subjects.retain(|x| Subject::is_user(username.clone())(&x));

        if subjects.len() == 0 {
            bindings_to_delete.insert(role_binding);
        } else {
            bindings_to_update.insert(role_binding);
        }
    }
    for role_binding in bindings_to_update {
        store_client::update(role_binding).await?;
    }
    for role_binding in bindings_to_delete {
        store_client::delete(role_binding).await?;
    }

    let mut roles = roles.clone();
    for x in existing_roles {
        roles.remove(&x);
    }

    for role_name in roles {
        let mut role_binding = RoleBinding::create(username.clone(), role_name);
        store_client::create(&mut role_binding).await?;
    }

    Ok(user)
}

pub async fn create_user(create_user_request: CreateUserRequest) -> AppResult<User> {
    if create_user_request.name.trim().is_empty() {
        return Err(anyhow::anyhow!("Name is required").into());
    }

    if create_user_request.email.trim().is_empty() {
        return Err(anyhow::anyhow!("Name is required").into());
    }
    let user = create_user_request.to_user();
    let user = create_user_with_role(user, create_user_request.roles.unwrap()).await?;
    update_with_raw_password(
        create_user_request.name,
        create_user_request.password.unwrap(),
    )
    .await?;
    Ok(user)
}

pub async fn create_user_with_role(user: User, role_names: HashSet<String>) -> AppResult<User> {
    let user: AppResult<User> = fetch(User::KIND, &user.get_metadata().name).await;

    // 用户已存在
    if user.is_ok() {
        Err(anyhow::anyhow!(
            "User name {} is already in use. problemDetail.user.duplicateName",
            user?.get_metadata().get_name()
        )
        .into())
    } else {
        for role_name in &role_names {
            let role: AppResult<Role> = fetch(role::Role::KIND, &role_name).await;
            if role.is_err() {
                return Err(anyhow::anyhow!("Role [{}] is not found.", role_name.clone()).into());
            }
        }
        let mut user = user?;
        store_client::create(&mut user).await?;
        grant_roles(user.get_metadata().get_name(), &role_names).await?;
        Ok(user)
    }
}

pub async fn update_with_raw_password(username: String, raw_password: String) -> AppResult<()> {
    let mut user = get_user(username).await?;
    let password = user.spec.password.clone();
    let mut set_password = false;
    if password.is_some() {
        let password = password.unwrap();
        // 密码不一样才修改
        if !rand_utils::verify_password(raw_password.clone(), password)
            .await
            .is_ok()
        {
            set_password = true;
        }
    } else {
        // Check if the old password is set before, or the passwordEncoder#matches
        // will complain an error due to null password.
        set_password = true;
    }
    if set_password {
        user.spec.password = Some(rand_utils::hash_password(raw_password).await?);
        store_client::update(user).await?
    }

    Ok(())
}

pub async fn get_user_permission(name: String, depot: &mut Depot) -> AppResult<UserPermission> {
    let username = depot
        .obtain::<Arc<LoginUserInfo>>()
        .map(|u| u.username.clone())
        .unwrap_or_default();

    //  let user = User {
    //             name: "salvo".to_string(),
    //         };
    //         let router = Router::with_hoop(inject(Arc::new(user)).insert("data1", "powerful")).goal(hello);
    //             depot.obtain::<Arc<User>>().map(|u| u.name.clone()).unwrap_or_default(),

    let role_names = &HashSet::new();
    return if SELF_USER == name {
        let roles = role_service::list(role_names).await?;
        let roles = HashSet::from_iter(roles);

        let permissions = role_service::list_permissions(role_names).await?;

        // TODO 不确定是否需要
        // roles.extend(permissions);

        let set: HashSet<Role> = HashSet::from_iter(permissions.clone());

        let ui_permissions = ui_permissions(&set);

        Ok(UserPermission {
            roles,
            permissions,
            ui_permissions,
        })
    } else {
        let roles = list_roles(username).await?;
        let roles: HashSet<Role> = HashSet::from_iter(roles);

        let role_names: HashSet<String> = roles
            .iter()
            .map(|t| t.get_metadata().get_name())
            //.cloned()
            .collect();

        let permissions = role_service::list_permissions(&role_names).await?;
        // TODO 不确定是否需要
        // roles.extend(permissions);
        let set: HashSet<Role> = HashSet::from_iter(permissions.clone());

        let ui_permissions = ui_permissions(&set);
        Ok(UserPermission {
            roles,
            permissions,
            ui_permissions,
        })
    };
}

fn ui_permissions(roles: &HashSet<Role>) -> HashSet<String> {
    if roles.is_empty() {
        return HashSet::new();
    }
    let mut set = HashSet::new();
    for role in roles {
        if let Some(annotations) = role.get_metadata().get_annotations() {
            if let Some(ui_permissions_json) = annotations.get(role::UI_PERMISSIONS_ANNO) {
                if let Ok(permissions_set) =
                    serde_json::from_str::<Vec<String>>(ui_permissions_json)
                {
                    set.extend(permissions_set);
                }
            }
        }
    }
    set
}

pub(crate) async fn list_roles(username: String) -> AppResult<Vec<Role>> {
    let vec: Vec<String> =
        store_client::list_filter(RoleBinding::KIND, RoleBinding::contains_user(username))
            .await?
            .iter()
            .filter(|&role_binding| role::Role::KIND == role_binding.role_ref.kind)
            .map(|r| r.role_ref.name.clone())
            .collect();

    let roles: Vec<Role> = store_client::list(role::Role::KIND, vec).await?;

    Ok(roles)
}

pub(crate) async fn change_password(
    username: String,
    current_username: String,
    change_password_request: ChangePasswordRequest,
) -> AppResult<User> {
    let username = if SELF_USER == username {
        current_username
    } else {
        username
    };

    let password = change_password_request.password;

    update_with_raw_password(username.clone(), password).await?;

    //TODO 返回update中的User，此处暂时使用查询代替
    Ok(store_client::fetch(User::KIND, &username).await?)
}

pub async fn list(list_request: UserListRequest) -> AppResult<ListResult<ListedUser>> {
    let options = list_request.to_list_options()?;
    let list = store_client::list_by::<User>(
        User::KIND,
        &options,
        &PageRequestImpl::new(
            list_request.page,
            list_request.size,
            list_request.get_sort(),
        ),
    )
    .await?;

    to_listed_user(list).await
}

pub async fn update_user_avatar(
    req: &mut Request,
    res: &mut Response,
    username: &str,
) -> AppResult<()> {
    let file = req.file("file").await;
    if let Some(file) = file {
        let filename = file.name().unwrap_or("file");
        if !filename.ends_with(".png") {
            return Err(AppError::err("Only support avatar in PNG format"));
        }

        let dest = format!("temp/{}", file.name().unwrap_or("file"));
         if let Err(e) = std::fs::copy(&file.path(), Path::new(&dest)) {
           
            format!("file not found in request: {}", e)
        } else {
            format!("File uploaded to {}", dest)
        };
        
    } else {
        return Err(AppError::err("No file part found in the request"));
    };
    Ok(())
}

pub async fn upload_avatar(file_part: &FilePart, filename: &str) -> AppResult<()> {
    if let Some(user_setting) = env_fetcher::fetch::<system_setting::User>(system_setting::USER_GROUP) {
        let mut avatar_policy = user_setting.avatar_policy;
        if avatar_policy.is_empty() {
            avatar_policy = DEFAULT_USER_AVATAR_ATTACHMENT_POLICY_NAME.to_string();
        }
        // 获取file_part 的文件后缀名
        let ext = Path::new(filename).extension().unwrap().to_str().unwrap();
        // attachment_service::create_attachment(
        //     &avatar_policy,
        //     file_part,
        //     format!("{}.{}", username, ext),
        // )
        // .await?;


        Ok(())
    } else {
        Err(AppError::err("User setting is not configured"))
    }
}

pub async fn to_listed_user(list_result: ListResult<User>) -> AppResult<ListResult<ListedUser>> {
    let items = &list_result.items;
    let usernames = items
        .iter()
        .map(|user| user.get_metadata().get_name())
        .collect::<Vec<_>>();

    let username_roles_map = get_roles_by_usernames(usernames).await?;

    let mut all_role_names = OrderSet::new();
    for (k, v) in &username_roles_map {
        for x in v {
            all_role_names.insert(x.clone());
        }
    }

    let role_list = list_role(all_role_names, false).await?;
    let mut role_map = HashMap::new();
    for role in role_list {
        role_map.insert(role.get_metadata().get_name(), role);
    }
    let mut user_list = Vec::new();
    for user in list_result.items {
        let username = user.get_metadata().get_name();

        let roles = username_roles_map
            .get(&username)
            .map(|role_names| {
                role_names
                    .iter()
                    .map(|role_name| role_map.get(role_name).unwrap().clone())
                    .collect::<Vec<_>>()
            })
            .unwrap_or_default();

        user_list.push(ListedUser { user, roles });
    }
    Ok(ListResult::new(
        list_result.page,
        list_result.size,
        list_result.total,
        user_list,
    ))
}

pub async fn list_role(role_names: OrderSet<String>, exclude_hidden: bool) -> AppResult<Vec<Role>> {
    if role_names.is_empty() {
        return Ok(Vec::new());
    }

    let not_deleting = not_deleting();

    let query = query_factory::and(
        not_deleting,
        Query::In(query_factory::in_query(
            "metadata.name".to_string(),
            role_names,
        )),
    )?;
    let mut label_selector = LabelSelector::new(Vec::new());

    if exclude_hidden {
        label_selector = LabelSelectorBuilder::builder()
            .not_eq(role::HIDDEN_LABEL_NAME.to_string(), "true".to_string())
            .build();
    }

    let field_selector = FieldSelector::of(query);
    let list_options = ListOptions::new(label_selector, field_selector);

    extension_client::list_all::<Role>(role::Role::KIND, &list_options, &default_sort()).await
}

pub async fn get_roles_by_usernames(
    usernames: Vec<String>,
) -> AppResult<HashMap<String, HashSet<String>>> {
    let subjects = usernames
        .iter()
        .map(|username| to_user_subject(username))
        .map(|subject| subject.to_string())
        .collect::<Vec<_>>();

    let not_deleting = not_deleting();

    let query = query_factory::and(
        not_deleting,
        Query::In(query_factory::in_query(
            "subjects".to_string(),
            OrderSet::from_iter(subjects.clone()),
        )),
    )?;

    let field_selector = FieldSelector::of(query);
    let label_selector = LabelSelector::new(Vec::new());
    let list_options = ListOptions::new(label_selector, field_selector);

    let sort = default_sort();

    let list =
        extension_client::list_all::<RoleBinding>(RoleBinding::KIND, &list_options, &sort).await?;

    let mut map = HashMap::new();

    for role_binding in &list {
        for subject in &role_binding.subjects {
            if subjects.contains(&subject.to_string()) {
                let role_ref = &role_binding.role_ref;
                if is_role_kind(role_ref) {
                    let role_name = role_ref.name.clone();
                    let username = subject.name.clone();
                    if !map.contains_key(&username) {
                        let mut set = HashSet::new();
                        set.insert(role_name);
                        map.insert(username, set);
                    } else {
                        if let Some(set) = map.get_mut(&username) {
                            set.insert(role_name);
                        }
                    }
                }
            }
        }
    }
    Ok(map)
}

fn not_deleting() -> Query {
    let not_deleting = Query::IsNull(query_factory::is_null(
        "metadata.deletionTimestamp".to_string(),
    ));
    not_deleting
}

fn is_role_kind(role_ref: &RoleRef) -> bool {
    role::GROUP == role_ref.api_group && role::Role::KIND == role_ref.kind
}

pub fn default_sort() -> Sort {
    let order1 = Order::new(Direction::Desc, "metadata.creationTimestamp".to_string());
    let order2 = Order::new(Direction::Asc, "metadata.name".to_string());
    Sort::new(vec![order1, order2])
}

fn to_user_subject(username: &String) -> Subject {
    Subject {
        kind: User::KIND.to_string(),
        name: username.to_string(),
        api_group: User::GROUP.to_string(),
    }
}

#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct ListedUser {
    user: User,
    roles: Vec<Role>,
}
